#pragma once
#include <utility>
#include <httplib.h>

#include "base.pb.h"
#include "user.pb.h"
#include "file.pb.h"
#include "message.pb.h"
#include "transmite.pb.h"
#include "speech.pb.h"
#include "friend.pb.h"
#include "gateway.pb.h"
#include "notify.pb.h"

#include "etcd.hpp"
#include "channel.hpp"
#include "utils.hpp"
#include "data_redis.hpp"

#include "connection.hpp"


#define GET_PHONE_VERIFY_CODE   "/service/user/get_phone_verify_code"
#define USERNAME_REGISTER       "/service/user/username_register"
#define USERNAME_LOGIN          "/service/user/username_login"
#define PHONE_REGISTER          "/service/user/phone_register"
#define PHONE_LOGIN             "/service/user/phone_login"
#define GET_USERINFO            "/service/user/get_user_info"
#define SET_USER_AVATAR         "/service/user/set_avatar"
#define SET_USER_NICKNAME       "/service/user/set_nickname"
#define SET_USER_DESC           "/service/user/set_description"
#define SET_USER_PHONE          "/service/user/set_phone"
#define FRIEND_GET_LIST         "/service/friend/get_friend_list"
#define FRIEND_APPLY            "/service/friend/add_friend_apply"
#define FRIEND_APPLY_PROCESS    "/service/friend/add_friend_process"
#define FRIEND_REMOVE           "/service/friend/remove_friend"
#define FRIEND_SEARCH           "/service/friend/search_friend"
#define FRIEND_GET_PENDING_EV   "/service/friend/get_pending_friend_events"
#define CSS_GET_LIST            "/service/friend/get_chat_session_list"
#define CSS_CREATE              "/service/friend/create_chat_session"
#define CSS_GET_MEMBER          "/service/friend/get_chat_session_member"
#define MSG_GET_RANGE           "/service/message_storage/get_history"
#define MSG_GET_RECENT          "/service/message_storage/get_recent"
#define MSG_KEY_SEARCH          "/service/message_storage/search_history"
#define NEW_MESSAGE             "/service/message_transmit/new_message"
#define FILE_GET_SINGLE         "/service/file/get_single_file"
#define FILE_GET_MULTI          "/service/file/get_multi_file"
#define FILE_PUT_SINGLE         "/service/file/put_single_file"
#define FILE_PUT_MULTI          "/service/file/put_multi_file"
#define SPEECH_RECOGNITION      "/service/speech/recognition"


class GatewayServer {
public:
    using ptr = std::shared_ptr<GatewayServer>;
    GatewayServer(int websocket_port,
                  int http_port,
                  const std::shared_ptr<sw::redis::Redis>& redis_client,
                  const ServiceManager::ptr& service_manager,
                  const Discovery::ptr& service_discoverer,
                  const std::string& file_service_name,
                  const std::string& friend_service_name,
                  const std::string& message_service_name,
                  const std::string& speech_service_name,
                  const std::string& transmite_service_name,
                  const std::string& user_service_name)
        : _redis_session(std::make_shared<Session>(redis_client))
        , _redis_status(std::make_shared<Status>(redis_client))
        , _service_manager(service_manager)
        , _service_discoverer(service_discoverer)
        , _connections(std::make_shared<Connection>())
        , _file_service_name(file_service_name)
        , _friend_service_name(friend_service_name)
        , _message_service_name(message_service_name)
        , _speech_service_name(speech_service_name)
        , _transmite_service_name(transmite_service_name)
        , _user_service_name(user_service_name) {

        // websocket服务器配置
        _websocket_server.init_asio();
        _websocket_server.set_access_channels(websocketpp::log::alevel::none);
        _websocket_server.set_message_handler(std::bind(&GatewayServer::onMessage, this, std::placeholders::_1, std::placeholders::_2));
        _websocket_server.set_open_handler(std::bind(&GatewayServer::onOpen, this, std::placeholders::_1));
        _websocket_server.set_close_handler(std::bind(&GatewayServer::onClosed, this, std::placeholders::_1));
        _websocket_server.set_reuse_addr(true);
        _websocket_server.listen(websocket_port);
        _websocket_server.start_accept();


        // http服务器配置
        // 注册用户服务相关接口
        _http_server.Post(GET_PHONE_VERIFY_CODE, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetPhoneVerifyCode(http_req, http_rsp);
        });
        _http_server.Post(USERNAME_REGISTER, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->UserRegister(http_req, http_rsp);
        });
        _http_server.Post(USERNAME_LOGIN, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->UserLogin(http_req, http_rsp);
        });
        _http_server.Post(PHONE_REGISTER, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->PhoneRegister(http_req, http_rsp);
        });
        _http_server.Post(PHONE_LOGIN, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->PhoneLogin(http_req, http_rsp);
        });
        _http_server.Post(GET_USERINFO, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetUserInfo(http_req, http_rsp);
        });
        _http_server.Post(SET_USER_AVATAR, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->SetUserAvatar(http_req, http_rsp);
        });
        _http_server.Post(SET_USER_NICKNAME, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->SetUserNickname(http_req, http_rsp);
        });
        _http_server.Post(SET_USER_DESC, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->SetUserDescription(http_req, http_rsp);
        });
        _http_server.Post(SET_USER_PHONE, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->SetUserPhoneNumber(http_req, http_rsp);
        });


        // 注册好友服务相关接口
        _http_server.Post(FRIEND_GET_LIST, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetFriendList(http_req, http_rsp);
        });
        _http_server.Post(FRIEND_REMOVE, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->FriendRemove(http_req, http_rsp);
        });
        _http_server.Post(FRIEND_APPLY, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->FriendAdd(http_req, http_rsp);
        });
        _http_server.Post(FRIEND_APPLY_PROCESS, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->FriendAddProcess(http_req, http_rsp);
        });
        _http_server.Post(FRIEND_SEARCH, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->FriendSearch(http_req, http_rsp);
        });
        _http_server.Post(FRIEND_GET_PENDING_EV, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetPendingFriendEventList(http_req, http_rsp);
        });
        _http_server.Post(CSS_GET_LIST, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetChatSessionList(http_req, http_rsp);
        });
        _http_server.Post(CSS_CREATE, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->ChatSessionCreate(http_req, http_rsp);
        });
        _http_server.Post(CSS_GET_MEMBER, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetChatSessionMember(http_req, http_rsp);
        });


        // 注册消息注册服务
        _http_server.Post(MSG_GET_RANGE, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetHistoryMsg(http_req, http_rsp);
        });
        _http_server.Post(MSG_GET_RECENT, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetRecentMsg(http_req, http_rsp);
        });
        _http_server.Post(MSG_KEY_SEARCH, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->MsgSearch(http_req, http_rsp);
        });


        // 注册消息转发服务相关接口
        _http_server.Post(NEW_MESSAGE, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetTransmitTarget(http_req, http_rsp);
        });


        // 注册文件服务相关接口
        _http_server.Post(FILE_GET_SINGLE, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetSingleFile(http_req, http_rsp);
        });
        _http_server.Post(FILE_GET_MULTI, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->GetMultiFile(http_req, http_rsp);
        });
        _http_server.Post(FILE_PUT_SINGLE, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->PutSingleFile(http_req, http_rsp);
        });
        _http_server.Post(FILE_PUT_MULTI, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->PutMultiFile(http_req, http_rsp);
        });


        // 注册语音识别服务相关接口
        _http_server.Post(SPEECH_RECOGNITION, [this](const httplib::Request &http_req, httplib::Response &http_rsp) {
            this->SpeechRecognition(http_req, http_rsp);
        });


        // 启动http服务器
        _http_thread = std::thread([this, http_port]() {
            LOG_INFO("HTTP服务器已启动, 监听端口: {}", http_port);
            _http_server.listen("0.0.0.0", http_port);
        });
        _http_thread.detach();

    }


    void start() {
        LOG_INFO("WebSocket服务器已启动");
        _websocket_server.run();
    }
public:
    void GetSingleFile(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetSingleFileReq rpc_req;
        chat_system::GetSingleFileRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取文件服务信道管理对象
        auto channel = getServiceChannel(_file_service_name);
        if(channel == nullptr) {
            err_handle("获取文件服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用文件服务的获取单个文件接口
        chat_system::FileService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetSingleFile(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取单个文件失败: {}", cntl.ErrorText());
            err_handle("获取单个文件失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            LOG_ERROR("获取单个文件失败: {}", rpc_rsp.errmsg());
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void GetMultiFile(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetMultiFileReq rpc_req;
        chat_system::GetMultiFileRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取文件服务信道管理对象
        auto channel = getServiceChannel(_file_service_name);
        if(channel == nullptr) {
            err_handle("获取文件服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用文件服务的获取单个文件接口
        chat_system::FileService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetMultiFile(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取多文件失败: {}", cntl.ErrorText());
            err_handle("获取多文件失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            LOG_ERROR("获取多文件失败: {}", rpc_rsp.errmsg());
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;

    }
    void PutSingleFile(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::PutSingleFileReq rpc_req;
        chat_system::PutSingleFileRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取文件服务信道管理对象
        auto channel = getServiceChannel(_file_service_name);
        if(channel == nullptr) {
            err_handle("获取文件服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用文件服务的上传单个文件接口
        chat_system::FileService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.PutSingleFile(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("上传单个文件失败: {}", cntl.ErrorText());
            err_handle("上传单个文件失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            LOG_ERROR("上传单个文件失败: {}", rpc_rsp.errmsg());
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void PutMultiFile(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::PutMultiFileReq rpc_req;
        chat_system::PutMultiFileRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取文件服务信道管理对象
        auto channel = getServiceChannel(_file_service_name);
        if(channel == nullptr) {
            err_handle("获取文件服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用文件服务的上传多个文件接口
        chat_system::FileService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.PutMultiFile(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("上传多个文件失败: {}", cntl.ErrorText());
            err_handle("上传多个文件失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            LOG_ERROR("上传多个文件失败: {}", rpc_rsp.errmsg());
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }
    

    void SpeechRecognition(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::SpeechRecognitionReq rpc_req;
        chat_system::SpeechRecognitionRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取语音识别服务信道管理对象
        auto channel = getServiceChannel(_speech_service_name);
        if(channel == nullptr) {
            err_handle("获取语音识别服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用语音识别服务的语音识别接口
        chat_system::SpeechService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SpeechRecognition(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("语音识别失败: {}", cntl.ErrorText());
            err_handle("语音识别失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            LOG_ERROR("语音识别失败: {}", rpc_rsp.errmsg());
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;    
    }


    void GetHistoryMsg(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetHistoryMsgReq rpc_req;
        chat_system::GetHistoryMsgRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取消息存储服务信道管理对象
        auto channel = getServiceChannel(_message_service_name);
        if(channel == nullptr) {
            err_handle("获取消息存储服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用消息存储服务的获取历史消息接口
        chat_system::MsgStorageService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetHistoryMsg(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取历史消息失败: {}", cntl.ErrorText());
            err_handle("获取历史消息失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void GetRecentMsg(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetRecentMsgReq rpc_req;
        chat_system::GetRecentMsgRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取消息存储服务信道管理对象
        auto channel = getServiceChannel(_message_service_name);
        if(channel == nullptr) {
            err_handle("获取消息存储服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用消息存储服务的获取最近消息接口
        chat_system::MsgStorageService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetRecentMsg(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取最近消息失败: {}", cntl.ErrorText());
            err_handle("获取最近消息失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void MsgSearch(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::MsgSearchReq rpc_req;
        chat_system::MsgSearchRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取消息存储服务信道管理对象
        auto channel = getServiceChannel(_message_service_name);
        if(channel == nullptr) {
            err_handle("获取消息存储服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用消息存储服务的消息搜索接口
        chat_system::MsgStorageService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.MsgSearch(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("消息搜索失败: {}", cntl.ErrorText());
            err_handle("消息搜索失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void GetTransmitTarget(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::NewMessageReq rpc_req;
        chat_system::GetTransmitTargetRsp rpc_rsp;
        chat_system::NewMessageRsp http_response;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取消息转发服务信道管理对象
        auto channel = getServiceChannel(_transmite_service_name);
        if(channel == nullptr) {
            err_handle("获取消息转发服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用消息转发服务的获取转发目标接口
        chat_system::MsgTransmitService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetTransmitTarget(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取转发目标失败: {}", cntl.ErrorText());
            err_handle("获取转发目标失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 处理转发
        for(const auto& target_id : rpc_rsp.target_id_list()) {
            auto conn = _connections->connection(target_id);
            if (!conn) {
                LOG_DEBUG("用户不在线, 无法转发消息, user_id: {}", target_id);
                continue;
            }
            try {
                chat_system::NotifyMessage notify;
                notify.set_notify_type(chat_system::NotifyType::CHAT_MESSAGE_NOTIFY);
                notify.mutable_new_message_info()->mutable_message_info()->CopyFrom(rpc_rsp.message());
                conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::BINARY);
            } catch(const websocketpp::exception& e) {
                LOG_ERROR("消息转发异常: {}, {}", e.what(), target_id);
            }
        }


        // 返回http响应
        http_response.set_success(rpc_rsp.success());
        http_response.set_errmsg(rpc_rsp.errmsg());
        http_response.set_request_id(rpc_req.request_id());
        http_rsp.set_content(http_response.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void GetFriendList(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetFriendListReq rpc_req;
        chat_system::GetFriendListRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }

        
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);

        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用好友服务的获取好友列表接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetFriendList(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取好友列表失败: {}", cntl.ErrorText());
            err_handle("获取好友列表失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }

    
    void FriendRemove(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::FriendRemoveReq rpc_req;
        chat_system::FriendRemoveRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }


        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);


        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用好友服务的删除好友接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.FriendRemove(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("删除好友失败: {}", cntl.ErrorText());
            err_handle("删除好友失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 向被删除的一方进行通知
        auto notify_conn = _connections->connection(rpc_req.peer_id());
        if(notify_conn) {
            try {
                chat_system::NotifyMessage notify;
                notify.set_notify_type(chat_system::NotifyType::FRIEND_REMOVE_NOTIFY);
                notify.mutable_friend_remove()->set_user_id(*user_id);
                notify_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::BINARY);
            } 
            catch(const websocketpp::exception& e) {
                LOG_ERROR("删除好友通知异常: {}", e.what());
            }
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void FriendAdd(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::FriendAddReq rpc_req;
        chat_system::FriendAddRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }


        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);


        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }

        
        // 调用好友服务的添加好友接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.FriendAdd(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("添加好友失败: {}", cntl.ErrorText());
            err_handle("添加好友失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 向被添加的一方进行通知
        auto notify_conn = _connections->connection(rpc_req.respondent_id());
        if(notify_conn) {
            try {
                chat_system::NotifyMessage notify;
                // 获取添加一方的用户信息
                std::unordered_map<std::string, chat_system::UserInfo> user_info;
                _GetUser(rpc_req.request_id(), {*user_id}, user_info);

                notify.set_notify_type(chat_system::NotifyType::FRIEND_ADD_APPLY_NOTIFY);
                notify.mutable_friend_add_apply()->mutable_user_info()->CopyFrom(user_info[*user_id]);
                notify_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::BINARY);
            } catch(const websocketpp::exception& e) {
                LOG_ERROR("添加好友通知异常: {}", e.what());
            }
        }

        
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void FriendAddProcess(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::FriendAddProcessReq rpc_req;
        chat_system::FriendAddProcessRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用好友服务的处理好友申请接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.FriendAddProcess(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("处理好友申请失败: {}", cntl.ErrorText());
            err_handle("处理好友申请失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 向申请添加的一方进行通知
        auto notify_conn = _connections->connection(rpc_req.apply_user_id());
        if(notify_conn) {
            try {
                chat_system::NotifyMessage notify;
                // 获取被添加一方的用户信息
                std::unordered_map<std::string, chat_system::UserInfo> user_info;
                _GetUser(rpc_req.request_id(), {*user_id}, user_info);

                notify.set_notify_type(chat_system::NotifyType::FRIEND_ADD_PROCESS_NOTIFY);
                notify.mutable_friend_process_result()->mutable_user_info()->CopyFrom(user_info[*user_id]);
                notify.mutable_friend_process_result()->set_agree(rpc_req.agree());
                notify_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::BINARY);
            } catch(const websocketpp::exception& e) {
                LOG_ERROR("处理好友申请通知异常: {}", e.what());
            }
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void FriendSearch(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::FriendSearchReq rpc_req;
        chat_system::FriendSearchRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }

        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);


        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用好友服务的搜索好友接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.FriendSearch(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("搜索好友失败: {}", cntl.ErrorText());
            err_handle("搜索好友失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void GetChatSessionList(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetChatSessionListReq rpc_req;
        chat_system::GetChatSessionListRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用好友服务的获取会话列表接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetChatSessionList(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取会话列表失败: {}", cntl.ErrorText());
            err_handle("获取会话列表失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void ChatSessionCreate(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::ChatSessionCreateReq rpc_req;
        chat_system::ChatSessionCreateRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用好友服务的创建会话接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.ChatSessionCreate(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("创建会话失败: {}", cntl.ErrorText());
            err_handle("创建会话失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 转发会话创建通知给会话成员
        for(const auto& member_id : rpc_req.member_id_list()) {
            if(member_id == *user_id) {
                continue;
            }
            auto notify_conn = _connections->connection(member_id);
            if(!notify_conn) {
                LOG_DEBUG("用户{}不在线, 无法发送会话创建通知", member_id);
                continue;
            }
            try {
                chat_system::NotifyMessage notify;
                notify.set_notify_type(chat_system::NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                notify.mutable_new_chat_session_info()->CopyFrom(rpc_rsp.chat_session_info());
                notify_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::BINARY);
            } catch(const websocketpp::exception& e) {
                LOG_ERROR("会话创建通知异常: {}", e.what());
            }
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void GetChatSessionMember(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetChatSessionMemberReq rpc_req;
        chat_system::GetChatSessionMemberRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);
        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用好友服务的获取会话成员接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetChatSessionMember(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取会话成员失败: {}", cntl.ErrorText());
            err_handle("获取会话成员失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void GetPendingFriendEventList(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetPendingFriendEventListReq rpc_req;
        chat_system::GetPendingFriendEventListRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }

        
        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);

        
        // 获取好友服务信道管理对象
        auto channel = getServiceChannel(_friend_service_name);
        if(channel == nullptr) {
            err_handle("获取好友服务信道失败");
            http_rsp.status = 500;
            return;
        }
        // 调用好友服务的获取待处理好友事件接口
        chat_system::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetPendingFriendEventList(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取待处理好友事件失败: {}", cntl.ErrorText());
            err_handle("获取待处理好友事件失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }



    void UserRegister(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::UserRegisterReq rpc_req;
        chat_system::UserRegisterRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }


        //获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的用户注册接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.UserRegister(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("用户注册失败: {}", cntl.ErrorText());
            err_handle("用户注册失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }

        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void UserLogin(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::UserLoginReq rpc_req;
        chat_system::UserLoginRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }


        //获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的用户登录接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.UserLogin(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("用户登录失败: {}", cntl.ErrorText());
            err_handle("用户登录失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }

        
        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }



    void GetPhoneVerifyCode(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::PhoneVerifyCodeReq rpc_req;
        chat_system::PhoneVerifyCodeRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }

        
        // 获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的获取手机验证码接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetPhoneVerifyCode(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取手机验证码失败: {}", cntl.ErrorText());
            err_handle("获取手机验证码失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }

    
    void PhoneRegister(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::PhoneRegisterReq rpc_req;
        chat_system::PhoneRegisterRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }

        
        //获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的手机注册接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.PhoneRegister(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("用户注册失败: {}", cntl.ErrorText());
            err_handle("用户注册失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }
        

        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }

    
    void PhoneLogin(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::PhoneLoginReq rpc_req;
        chat_system::PhoneLoginRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);    
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }


        //获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }

        
        // 调用用户服务的手机登录接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.PhoneLogin(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("用户登录失败: {}", cntl.ErrorText());
            err_handle("用户登录失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }

        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }

    
    void GetUserInfo(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::GetUserInfoReq rpc_req;
        chat_system::GetUserInfoRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);    
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }


        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);


        //获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的获取用户信息接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetUserInfo(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("获取用户信息失败: {}", cntl.ErrorText());
            err_handle("获取用户信息失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }



    void SetUserAvatar(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::SetUserAvatarReq rpc_req;
        chat_system::SetUserAvatarRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);    
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }


        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);


        //获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的设置用户头像接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserAvatar(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("用户设置头像失败: {}", cntl.ErrorText());
            err_handle("用户设置头像失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }


    void SetUserNickname(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::SetUserNicknameReq rpc_req;
        chat_system::SetUserNicknameRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);    
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }


        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);


        //获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的设置用户昵称接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserNickname(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("用户设置昵称失败: {}", cntl.ErrorText());
            err_handle("用户设置昵称失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    } 

    
    void SetUserDescription(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::SetUserDescriptionReq rpc_req;
        chat_system::SetUserDescriptionRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);    
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }    
        

        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);


        // 获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的设置用户签名接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserDescription(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("用户设置签名失败: {}", cntl.ErrorText());
            err_handle("用户设置签名失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    } 


    void SetUserPhoneNumber(const httplib::Request &http_req, httplib::Response &http_rsp) {
        // 从http请求中解析出rpc请求
        chat_system::SetUserPhoneNumberReq rpc_req;
        chat_system::SetUserPhoneNumberRsp rpc_rsp;
        auto err_handle = [&http_rsp, &rpc_req, &rpc_rsp](const std::string& err_msg) {
            rpc_rsp.set_success(false);
            rpc_rsp.set_errmsg(err_msg);
            rpc_rsp.set_request_id(rpc_req.request_id());
            http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool success = rpc_req.ParseFromString(http_req.body);    
        if (!success) {
            err_handle("http请求数据解析错误");
            http_rsp.status = 400;
            return;
        }    
        

        // 对客户端鉴权
        std::string login_session_id = rpc_req.session_id();
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            err_handle("用户未登录");
            http_rsp.status = 401;
            return;
        }
        rpc_req.set_user_id(*user_id);


        // 获取用户服务信道管理对象
        auto channel = getServiceChannel(_user_service_name);
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            http_rsp.status = 500;
            return;
        }


        // 调用用户服务的设置用户电话接口
        chat_system::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserPhoneNumber(&cntl, &rpc_req, &rpc_rsp, nullptr);
        if (cntl.Failed()) {
            LOG_DEBUG("用户设置电话失败: {}", cntl.ErrorText());
            err_handle("用户设置电话失败");
            http_rsp.status = 500;
            return;
        }
        if (!rpc_rsp.success()) {
            err_handle(rpc_rsp.errmsg());
            http_rsp.status = 500;
            return;
        }


        // 返回http响应
        http_rsp.set_content(rpc_rsp.SerializeAsString(), "application/x-protbuf");
        http_rsp.status = 200;
    }
private:
    ServiceChannel::ChannelPtr getServiceChannel(const std::string& service_name) {
        //获取服务信道管理对象
        auto channel_manager = _service_manager->choose(service_name);
        if(channel_manager == nullptr) {
            LOG_DEBUG("获取服务[{}]信道失败", service_name);
            return nullptr;
        }
        // 获取服务信道
        auto channel = channel_manager->choose();
        if(channel == nullptr) {
            LOG_DEBUG("获取服务[{}]信道失败", service_name);
            return nullptr;
        }
        return channel;
    }

    bool _GetUser(const std::string &req_id,
                  const std::unordered_set<std::string> &user_ids,
                  std::unordered_map<std::string, chat_system::UserInfo> &user_info) {
        //获取用户服务信道管理对象
        auto channel_manager = _service_manager->choose(_user_service_name);
        if(channel_manager == nullptr) {
            LOG_ERROR("获取用户服务信道失败");
            return false;
        }
        // 获取用户服务信道
        auto channel = channel_manager->choose();
        if(channel == nullptr) {
            LOG_ERROR("获取用户服务信道失败");
            return false;
        }
        
        
        // 向用户管理子服务发起RPC调用, 获取用户信息
        chat_system::UserService_Stub stub(channel.get());
        chat_system::GetMultiUserInfoReq req;
        chat_system::GetMultiUserInfoRsp rsp;
        req.set_request_id(req_id);
        for(const auto& user_id : user_ids) {
            if(user_id.empty()) continue;
            req.add_users_id(user_id);
        }

        brpc::Controller cntl;  
        stub.GetMultiUserInfo(&cntl, &req, &rsp, nullptr);
        LOG_DEBUG("---{}---{}---", cntl.Failed(), rsp.success());
        if(cntl.Failed() || !rsp.success()) {
            LOG_ERROR("获取用户信息失败: {}---{}---", rsp.errmsg(), cntl.ErrorText());
            return false;
        }

        // 获取用户信息成功
        for(const auto& user : rsp.users_info()) {
            user_info.insert(std::make_pair(user.first, user.second));
        }
        return true;
    }   

private:
    void keepAlive(websocket_server_t::connection_ptr conn) {
        if (!conn || conn->get_state() != websocketpp::session::state::value::open) {
            LOG_DEBUG("非正常连接状态，结束连接保活");
            return;
        }
        conn->ping("");
        _websocket_server.set_timer(60000, [this, conn](const std::error_code){
            keepAlive(conn);
        });
    }


    void onMessage(websocketpp::connection_hdl hdl, websocket_server_t::message_ptr msg) {
        // 获取连接
        auto con = _websocket_server.get_con_from_hdl(hdl);
        if (!con) {
            LOG_ERROR("获取WebSocket连接失败");
            return;
        }

        // 反序列化msg载荷
        chat_system::ClientAuthenticationReq websocket_req;
        bool success = websocket_req.ParseFromString(msg->get_payload());
        if (!success) {
            LOG_ERROR("WebSocket请求数据解析错误, {}", (size_t)con.get());
            _websocket_server.close(hdl, websocketpp::close::status::invalid_payload, "请求数据解析错误");
            return;
        }

        // 获取客户端的登录session_id
        std::string login_session_id = websocket_req.session_id();
        if (login_session_id.empty()) {
            LOG_ERROR("WebSocket请求数据中缺少登录session_id, {}", (size_t)con.get());
            _websocket_server.close(hdl, websocketpp::close::status::invalid_payload, "请求数据中缺少登录session_id");
            return;
        }


        // 查询出用户ID
        auto user_id = _redis_session->user_id(login_session_id);
        if(!user_id) {
            LOG_ERROR("WebSocket客户端未登录, session_id: {}, {}", login_session_id, (size_t)con.get());
            _websocket_server.close(hdl, websocketpp::close::status::policy_violation, "用户未登录");
            return;
        }


        // 将连接加入连接管理器
        _connections->insert(con, *user_id, login_session_id);
        keepAlive(con);
    }

    
    void onOpen(websocketpp::connection_hdl hdl) {
        LOG_INFO("WebSocket长连接建立成功, {}", (size_t)_websocket_server.get_con_from_hdl(hdl).get());
    }

    
    void onClosed(websocketpp::connection_hdl hdl) {
        // 获取连接
        auto con = _websocket_server.get_con_from_hdl(hdl);
        if (!con) {
            LOG_ERROR("获取WebSocket连接失败");
            return;
        }


        // 从连接管理器中获取用户信息
        std::string user_id, login_session_id;
        _connections->client(con, user_id, login_session_id);
        if(user_id.empty() || login_session_id.empty()) {
            LOG_ERROR("获取WebSocket连接的用户信息失败, {}", (size_t)con.get());
            return;
        }


        // 清除登录会话信息
        _redis_session->remove(login_session_id);
        _redis_status->remove(user_id);


        // 清除长连接
        _connections->remove(con);
        websocketpp::lib::error_code err_code;
        if(con->get_state() != websocketpp::session::state::value::closed)
            con->close(websocketpp::close::status::normal, "连接关闭", err_code);
        if(err_code) {
            LOG_DEBUG("连接状态: ", int(con->get_state()));
            LOG_ERROR("WebSocket连接关闭失败, {}, {}", err_code.message(), (size_t)con.get());
            return;
        }
        LOG_INFO("WebSocket长连接已关闭, user_id: {}, session_id: {}, {}", user_id, login_session_id, (size_t)con.get());
    }
private:
    Session::ptr _redis_session;    
    Status::ptr _redis_status;

    ServiceManager::ptr _service_manager;
    Discovery::ptr _service_discoverer;

    websocket_server_t _websocket_server;
    httplib::Server _http_server;
    std::thread _http_thread;

    Connection::ptr _connections;
    
    std::string _file_service_name;
    std::string _friend_service_name;
    std::string _message_service_name;
    std::string _speech_service_name;
    std::string _transmite_service_name;
    std::string _user_service_name;
};


class GatewayServerBuilder { 
public:
    void make_redis_object(const std::string& ip, int port, int db, bool keep_alive = true) {
        _redis_client = RedisClientFactory::create(ip, port, db, keep_alive);
    }
    //用于构造服务发现客户端&信道管理对象
    void make_discovery_object(const std::string &reg_host,
        const std::string &basedir,
        const std::string &file_service_name,
        const std::string &speech_service_name,
        const std::string &message_service_name,
        const std::string &friend_service_name,
        const std::string &user_service_name,
        const std::string &transmite_service_name) {
        _file_service_name      = basedir + file_service_name;
        _speech_service_name    = basedir + speech_service_name;
        _message_service_name   = basedir + message_service_name;
        _friend_service_name    = basedir + friend_service_name;
        _user_service_name      = basedir + user_service_name;
        _transmite_service_name = basedir + transmite_service_name;
        _service_manager = std::make_shared<ServiceManager>();
        LOG_DEBUG("-------------------{}------------------", _user_service_name);
        _service_manager->declared(_file_service_name);
        _service_manager->declared(_speech_service_name);
        _service_manager->declared(_message_service_name);
        _service_manager->declared(_friend_service_name);
        _service_manager->declared(_user_service_name);
        _service_manager->declared(_transmite_service_name);
        auto put_cb = std::bind(&ServiceManager::onServiceOnline, _service_manager, std::placeholders::_1, std::placeholders::_2);
        auto del_cb = std::bind(&ServiceManager::onServiceOffline, _service_manager, std::placeholders::_1, std::placeholders::_2);
        _service_discoverer = std::make_shared<Discovery>(reg_host, basedir, put_cb, del_cb);
    }


    void make_server_object(int websocket_port, int http_port) {
        _websocket_port = websocket_port;
        _http_port = http_port;
    }


    GatewayServer::ptr build() {
        if(_service_discoverer == nullptr)
        {
            LOG_ERROR("服务发现对象未创建");
            return nullptr;
        }

        return std::make_shared<GatewayServer>(_websocket_port,
                                               _http_port,
                                               _redis_client,
                                               _service_manager,
                                               _service_discoverer,
                                               _file_service_name,
                                               _friend_service_name,
                                               _message_service_name,
                                               _speech_service_name,
                                               _transmite_service_name,
                                               _user_service_name);
    }
private:

    std::string _file_service_name;
    std::string _friend_service_name;
    std::string _message_service_name;
    std::string _speech_service_name;
    std::string _transmite_service_name;
    std::string _user_service_name;
    
    ServiceManager::ptr _service_manager;
    Discovery::ptr _service_discoverer;

    std::shared_ptr<sw::redis::Redis>_redis_client;

    int _websocket_port = 0;
    int _http_port = 0;
};    
